package com.keguoyu.easymvp.business;

import java.util.List;

import androidx.annotation.NonNull;

import com.google.common.collect.ImmutableList;
import com.keguoyu.easymvp.commons.receiver.MultiReceiverImpl;
import com.keguoyu.easymvp.commons.receiver.ReceiverInterface;
import com.keguoyu.easymvp.commons.receiver.Receivers;
import com.keguoyu.easymvp.commons.supplier.SupplierContainer;
import com.keguoyu.easymvp.commons.supplier.SupplierGenerator;
import com.keguoyu.easymvp.commons.supplier.SupplierInterface;
import com.keguoyu.easymvp.receiver.AutoWiredReceiver;

/**
 * @author keguoyu
 * @version 1.0.2
 */
@SuppressWarnings("unchecked")
public final class AutoWiredExtension implements AutoWiredReceiver {
  private final Object mTarget;

  private SupplierContainer mInitialWrapper = new SupplierContainer();
  private final ReceiverInterface<Object> mReceiverInterface;

  private boolean mHasInjected;

  public AutoWiredExtension(Object target) {
    mTarget = target;
    ImmutableList.Builder<ReceiverInterface<Object>> builder = ImmutableList.builder();

    List<ReceiverInterface<Object>> list = Receivers.receiverList(target);

    for (Object item: list) {
      builder.add((ReceiverInterface<Object>)item);
    }

    mReceiverInterface = new MultiReceiverImpl<Object>(builder.build());
  }

  SupplierContainer buildSupplierContainer(Object... src) {
    SupplierContainer supplierContainer;
    if (src != null && src.length == 1 && src[0] instanceof SupplierContainer) {
      if (mInitialWrapper.isEmpty()) {
        supplierContainer = (SupplierContainer) src[0];
      } else {
        supplierContainer = new SupplierContainer();
        supplierContainer.copy(mInitialWrapper);
        supplierContainer.copy((SupplierContainer) src[0]);
      }
    } else {
      supplierContainer = new SupplierContainer();
      supplierContainer.copy(mInitialWrapper);
      if (src != null) {
        for (Object context : src) {
          SupplierGenerator.me().factory(context).addToWrapper(supplierContainer,
              context);
        }
      }
    }
    return supplierContainer;
  }

  void receive(SupplierContainer supplierContainer) {
    mReceiverInterface.receive(mTarget, supplierContainer);
    mHasInjected = true;
  }

  @Override
  public void addToProvider(@NonNull Object src) {
    SupplierInterface<Object> factory = SupplierGenerator.me().factory(src);
    if (factory != null) {
      factory.addToWrapper(mInitialWrapper, src);
    }
  }

  @Override
  public void autoWire(Object... objects) {
    SupplierContainer supplierContainer = buildSupplierContainer(objects);
    receive(supplierContainer);
  }

  @Override
  public void reset() {
    mReceiverInterface.reset(mTarget);
    mHasInjected = false;
  }

  @Override
  public boolean available() {
    return !mHasInjected;
  }

}
